package com.umeox.watch.moto.dataservice.base;

import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static com.umeox.moto.common.log.Logger.getTime;
import static com.umeox.watch.moto.dataservice.mqtt.service.MqttService.KEY_LAST_HANDLE_INTENT;

import android.annotation.SuppressLint;
import android.app.AlarmManager;
import android.app.Dialog;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.ContentObserver;
import android.os.BatteryManager;
import android.os.Build;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
import android.view.WindowManager;

import com.umeox.moto.common.log.Logger;
import com.umeox.moto.common.ui.CommonDialog;
import com.umeox.moto.common.utils.AndroidUtils;
import com.umeox.moto.common.utils.DeviceManager;
import com.umeox.moto.common.utils.NetUtils;
import com.umeox.moto.common.utils.SystemUtils;
import com.umeox.watch.moto.dataservice.DataProvider;
import com.umeox.watch.moto.dataservice.constants.Constants;
import com.umeox.watch.moto.dataservice.constants.InternalConstant;
import com.umeox.watch.moto.dataservice.db.AppDataBase;
import com.umeox.watch.moto.dataservice.db.dao.DeviceCodeDao;
import com.umeox.watch.moto.dataservice.db.dao.DeviceDao;
import com.umeox.watch.moto.dataservice.db.model.DeviceCode;
import com.umeox.watch.moto.dataservice.db.model.DeviceConfig;
import com.umeox.watch.moto.dataservice.db.model.ForbidPeriod;
import com.umeox.watch.moto.dataservice.db.model.ForbidPeriods;
import com.umeox.watch.moto.dataservice.db.model.ServerConfig;
import com.umeox.watch.moto.dataservice.mqtt.ConnectConfig;
import com.umeox.watch.moto.dataservice.mqtt.impl.MqttServiceDelegate;
import com.umeox.watch.moto.dataservice.mqtt.service.MqttService;
import com.umeox.watch.moto.dataservice.observer.CellInfoObserver;
import com.umeox.watch.moto.dataservice.observer.FalloffObserver;
import com.umeox.watch.moto.dataservice.observer.GalleryContentObserver;
import com.umeox.watch.moto.dataservice.receiver.AlarmReceiver;
import com.umeox.watch.moto.dataservice.receiver.LocationReceiver;
import com.umeox.watch.moto.dataservice.services.ApiService;
import com.umeox.watch.moto.dataservice.stub.ChatStub;
import com.umeox.watch.moto.dataservice.stub.LocationStub;
import com.umeox.watch.moto.dataservice.stub.PairStub;
import com.umeox.watch.moto.dataservice.stub.PullApiClientStub;
import com.umeox.watch.moto.dataservice.stub.PushApiClientStub;
import com.umeox.watch.moto.dataservice.stub.VideocallStub;
import com.umeox.watch.moto.dataservice.utils.CountDownTimer;

import java.util.List;
import java.util.Locale;
import java.util.TimeZone;

/**
 * 设备启动配置管理
 */
public class LauncherManager {

    public static final int MILLIS_IN_FUTURE = 10000;
    public static final int DOWN_INTERVAL = 100;
    public static final String KEY_FIRST_LAUNCHER = "first_launcher";
    public static final String KEY_LAST_INIT_MQTT = "init_mqtt";
    public static final String TIME_AUTO = "TIME_AUTO";
    private Context mContext;
    private boolean mConfigurationCompleted;
    private boolean mIsActivated;
    private static final String TAG = Constants.TAG;
    public static final String ACTION_SIM_STATE_CHANGED = "android.intent.action.SIM_STATE_CHANGED";
    private TelephonyManager mTm;
    private long mTime;
    private String mDeviceId;
    private ForbidPeriods forbidPeriods;
    private boolean mDataRequested;
    private ConnectConfig configure;
    private DeviceConfig mDeviceConfig;
    private String mCurrTimeZone;
    private int mFallOffAlarmSatus;
    private int mProhibitShutdownStatus;

    public ConnectConfig getConfigure() {
        return configure;
    }

    public void setConfigure(ConnectConfig configure) {
        this.configure = configure;
    }

    /**
     * 初始化
     *
     * @param context
     */
    public void initialize(Context context) {
        mContext = context;
        BaseApp.getInstance().getMmkv().encode(KEY_LAST_HANDLE_INTENT, 0L);
        final boolean aBoolean = BaseApp.getInstance().getMmkv().decodeBool(TIME_AUTO, false);
        if (!aBoolean) {
            mCurrTimeZone = "";
            Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AUTO_TIME, 1);
            BaseApp.getInstance().getMmkv().encode(TIME_AUTO, true);
        }
        setTimeAutoEnable(true);
        mTime = getTime(0);
        mTm = (TelephonyManager) context.getSystemService(Service.TELEPHONY_SERVICE);
        registerObserver();
        mCountDownTimer.start();
        mIsActivated = DataProvider.isActivated();
        //初始化时 清除加密缓存 使用后记得注释
//        BaseApp.getInstance().getMmkv().clear();

        try {
            if(!DeviceManager.getInstance().isOverlayScreenOn()){
                DeviceManager.getInstance().setOverlayScreenValue(true);
            }
//            DeviceManager.getInstance().setRaiseUpValue(Settings.System.getInt(context.getContentResolver(), "raise_up") == 1);
        } catch (Exception e) {
            e.printStackTrace();
        }





    }


    /**
     * 设备是否已经配置完成
     *
     * @return
     */
    public boolean isConfigurationCompleted() {
        return mConfigurationCompleted;
    }

    /**
     * 设备绑定状态
     *
     * @return
     */
    public boolean isActivated() {
        return mIsActivated;
    }


    /**
     * 注册监听
     */
    public void registerObserver() {
        mContext.getContentResolver().registerContentObserver(DataProvider.DeviceCodeProvider.getUri(), false, mDeviceInfoObserver);
        mContext.registerReceiver(mBroadcastReceiver, new IntentFilter(ACTION_SIM_STATE_CHANGED));
        mContext.registerReceiver(mNetWorkReceiver, new IntentFilter(CONNECTIVITY_ACTION));
    }

    /**
     * 取消监听
     */
    public void unRegisterObserver() {
        mContext.getContentResolver().unregisterContentObserver(mDeviceInfoObserver);
    }

    public void initMqtt(String deviceId) {

        if (TextUtils.isEmpty(deviceId)) {
            return;
        }
        configure = new ConnectConfig(deviceId);

        boolean running = MqttService.getInstance().isRunning();
        boolean connected = MqttService.getInstance().isConnected();

        Log.d(TAG, "initMqtt: " + running + " connected:" + connected);
        if (running && connected) {
            //获取deviceConfig
            ApiService.getDeviceConfig();
            ApiService.getDeviceCode();
        } else {
            //Start service if not started
            MqttServiceDelegate.startService(mContext);
        }

    }

    private final ContentObserver mDeviceInfoObserver = new ContentObserver(null) {
        @Override
        public void onChange(boolean selfChange) {
            String bindCode = DataProvider.getBindCode();
            Log.d(TAG, "onChange mIsActivated:" + mIsActivated + " bindCode:" + bindCode);
            if (TextUtils.isEmpty(bindCode)) {
                return;
            }
            mConfigurationCompleted = true;
        }
    };


    private final CountDownTimer mCountDownTimer = new CountDownTimer(MILLIS_IN_FUTURE, DOWN_INTERVAL) {
        @Override
        public void onTick(long millisUntilFinished) {
            mDeviceId = AndroidUtils.getDeviceId();
            if (!TextUtils.isEmpty(mDeviceId)) {
                BaseApp.getInstance().deviceId = mDeviceId;
                initLocalConfig(mDeviceId);
                cancel();
                if (mDataRequested) {
                    return;
                }
                onNetworkAvailable();
                cancel();
            }
        }

        @Override
        public void onFinish() {
            Logger.e(TAG, "onFinish: deviceId must be not null ");
            Dialog dialog = CommonDialog.createLoadingDialog(mContext, "请确保该设备写入了IMEI");
            if (dialog.getWindow() != null) {
                dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
                dialog.show();
            } else {
                android.os.Process.killProcess(android.os.Process.myPid());
                System.exit(0);
            }
        }
    };

    private void initLocalConfig(String deviceId) {
        DeviceDao deviceDao = AppDataBase.getInstance().deviceDao();
        DeviceCodeDao deviceCodeDao = AppDataBase.getInstance().deviceCodeDao();
        DeviceConfig config = deviceDao.queryByDeviceId(deviceId);
        if (config == null) {
            config = new DeviceConfig();
            config.setDeviceId(deviceId);
            deviceDao.save(config);
            Logger.d(TAG + ">>>>>>>>>init device config<<<<<<<<<");
        }
        DeviceCode deviceCode = deviceCodeDao.queryByDeviceId(deviceId);
        if (deviceCode == null) {
            deviceCode = new DeviceCode();
            deviceCode.setDeviceId(deviceId);
            deviceCodeDao.save(deviceCode);
            Logger.d(TAG + ">>>>>>>>>init device code config<<<<<<<<<");
        }
        //监听相册内容，用于上传照片到服务器
        GalleryContentObserver.getInstance().registerGalleryContentObserver();
        //监听基站信息变化
        CellInfoObserver.getInstance().registerObserver();
        //注册Binder服务
        Logger.d(TAG + ">>>>>>>>>start register binder<<<<<<<<<");
        ChatStub.registerBinder();
        PairStub.registerBinder();
        PullApiClientStub.registerBinder();
        PushApiClientStub.registerBinder();
        VideocallStub.registerBinder();
        LocationStub.registerBinder();
        Logger.d(TAG + ">>>>>>>>>register plugin done<<<<<<<<<");
        checkAlarm(true);
        checkProhibitShutdownState(config.getForbiddenShutdown());
        checkRefusePhoneState(config.getWhiteList());
        checkFallOffAlarmState(config.getOffAlarm());
    }

    @SuppressLint("WrongConstant")
    public int getBatteryLevel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            BatteryManager batteryManager = (BatteryManager) mContext.getSystemService(Context.BATTERY_SERVICE);
            return batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY);
        } else {
            Intent intent = mContext.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
            return intent != null ? intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) : 0;
        }
    }

    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();

            if (action == null) {
                return;
            }

            if (action.equals(ACTION_SIM_STATE_CHANGED)) {
                int state = mTm.getSimState();
                final String deviceId = AndroidUtils.getDeviceId();
                Logger.i(TAG, "onReceive: " + state + " " + deviceId);
                if (state == TelephonyManager.SIM_STATE_READY) {
                    mContext.unregisterReceiver(this);
                    setupMobileData();
                }
            }
        }
    };

    private final BroadcastReceiver mNetWorkReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (CONNECTIVITY_ACTION.equals(intent.getAction())) {
                if (NetUtils.isNetworkAvailable()) {
                    Log.d(TAG, "onReceive: Network Available " + getTime(mTime));
                    mContext.unregisterReceiver(this);
                    if (!TextUtils.isEmpty(mDeviceId)) {
                        mDataRequested = true;
                        onNetworkAvailable();
                    }
                }
            }
        }
    };

    private void setupMobileData() {
        if (!SystemUtils.getDataEnabled(mContext)) {
            SystemUtils.setDataEnabled(mContext, true);
        }
    }


    public synchronized void onNetworkAvailable() {
        Log.i(TAG, "onNetworkAvailable: initMqtt " + getTime(mTime) + " mDeviceId:" + mDeviceId + " mConfigurationCompleted:" + mConfigurationCompleted);
//        if (mConfigurationCompleted) return;

        initMqtt(mDeviceId);
    }

    /**
     * 重置有时间范围限制的闹钟
     * 计步数据上报不需要重置
     */
    public void resetAlarm() {
        Logger.w(TAG + ">>>重置日期时间相关闹钟");
        //上报记步闹钟
//        mContext.sendBroadcast(new Intent(mContext, AlarmReceiver.class)
//                .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)
//                .setAction(InternalConstant.ACTION_UPLOAD_STEP_ALARM));
        //定位闹钟
        mContext.sendBroadcast(new Intent(mContext, LocationReceiver.class)
                .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)
                .setAction(InternalConstant.ACTION_RESET_LOCATION_ALARM));
        //上课模式闹钟
        mContext.sendBroadcast(new Intent(mContext, AlarmReceiver.class)
                .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)
                .setAction(InternalConstant.ACTION_RESET_STUDY_MODE_ALARM));
    }

    public String getFileHost() {
        ServerConfig serverConfig = getServerConfig();
        if (serverConfig != null) {
            return String.format(Locale.ENGLISH, "http://%s:%d", serverConfig.getFileServerAddress(), serverConfig.getFileServerPort());
        }
        return "";
    }

    public String getAPIHost() {
        ServerConfig serverConfig = getServerConfig();
        if (serverConfig != null) {
            if (serverConfig.getSslSupport() == 1) {
                return String.format(Locale.getDefault(), "%s:%d", serverConfig.getSslServerAddress(), serverConfig.getSslServerPort());
            } else {
                return String.format(Locale.getDefault(), "%s:%d", serverConfig.getServerAddress(), serverConfig.getServerPort());
            }
        }
        return "";
    }

    public ServerConfig getServerConfig() {
        return AppDataBase.getInstance().serverConfigDao().query(mDeviceId);
    }

    private void initForbidPeriods() {
        forbidPeriods = new ForbidPeriods();
        forbidPeriods.setClassTimeList(AppDataBase.getInstance().forbidPeriodDao().query(mDeviceId));
    }

    public ForbidPeriods getForbidPeriods() {
        if (forbidPeriods == null) {
            initForbidPeriods();
        }
        return forbidPeriods;
    }

    public void setForbidPeriods(List<ForbidPeriod> forbidPeriods) {
        getForbidPeriods().setClassTimeList(forbidPeriods);
        Intent intent = new Intent();
        intent.setAction(InternalConstant.ACTION_RESET_STUDY_MODE_ALARM);
        intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES | Intent.FLAG_RECEIVER_FOREGROUND);
        mContext.sendBroadcast(intent);
    }

    public void sendResetClassModeBroadcast() {
        Intent intent = new Intent();
        intent.setAction(InternalConstant.ACTION_RESET_STUDY_MODE_ALARM);
        intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES | Intent.FLAG_RECEIVER_FOREGROUND);
        mContext.sendBroadcast(intent);
    }

    /**
     * 开机检查所有闹钟是否设置
     */
    public void checkAlarm(boolean reset) {
        Logger.i(TAG + ">>>检查各种业务闹钟是否有设置");
        //判断定位闹钟
        Intent locIntent = new Intent(mContext, LocationReceiver.class);
        locIntent.setAction(InternalConstant.ACTION_RESET_LOCATION_ALARM);
        boolean locAlarmUp = (PendingIntent.getBroadcast(mContext, InternalConstant.REQUEST_CODE_LOCATION,
                locIntent, PendingIntent.FLAG_NO_CREATE) != null);
        if (BaseApp.isActivated() && (!locAlarmUp || reset)) {
            Logger.i("定位服务未启动，开启服务");
            mContext.sendBroadcast(locIntent);
        }

        mContext.sendBroadcast(new Intent(mContext, AlarmReceiver.class).setAction(InternalConstant.ACTION_RESET_STUDY_MODE_ALARM));

    }

    public static LauncherManager getInstance() {
        return InstanceHolder.instance;
    }

    public void destroy() {
        unRegisterObserver();
    }


    /**
     * 设备信息发生改变
     *
     * @param deviceConfig
     */
    public void onDeviceConfigChange(DeviceConfig deviceConfig) {
        mDeviceConfig = deviceConfig;
        mIsActivated = mDeviceConfig != null && mDeviceConfig.isActivated();
        if (deviceConfig != null) {
            checkFallOffAlarmState(deviceConfig.getOffAlarm());
            checkRefusePhoneState(deviceConfig.getWhiteList());
            checkProhibitShutdownState(deviceConfig.getForbiddenShutdown());
        }
    }

    private static class InstanceHolder {
        @SuppressLint("StaticFieldLeak")
        private static final LauncherManager instance = new LauncherManager();
    }


    public boolean setTimeAutoEnable(Boolean autoEnabled) {
        Settings.Global.putInt(mContext.getContentResolver()
                , Settings.Global.AUTO_TIME
                , autoEnabled ? 1 : 0);
        return true;
    }


    /**
     * 修改系统时区
     *
     * @param timeZone America/Chihuahua(GMT-06:00)
     */
    public void setTimeZone(String timeZone) {
        Logger.d(TAG, "setTimeZone Default: " + TimeZone.getDefault().getID() + " timeZone:" + timeZone);
        if (TextUtils.equals(mCurrTimeZone, timeZone)) {
            return;
        }
        mCurrTimeZone = timeZone;
        if (TextUtils.isEmpty(timeZone)) {
            Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AUTO_TIME, 1);
            BaseApp.getInstance().getMmkv().encode(TIME_AUTO, true);
            return;
        }
        try {
            if (timeZone.contains("(")) {
                timeZone = timeZone.replaceAll("\\(", "#").replaceAll("\\)", "").split("#")[1];
            }
            final AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
            alarmManager.setTimeZone(timeZone);
        } catch (Exception e) {
            Logger.e(TAG, "setTimeZone: ", e);
        }
    }


    /**
     * 检查设备状态，判断是否需要发送开启/关闭白名单功能
     */
    @SuppressLint("WrongConstant")
    public void checkRefusePhoneState(int currentStatus) {
        Log.d(TAG, "checkRefusePhoneState: " + currentStatus);
        Settings.System.putInt(mContext.getContentResolver(), "refuse_phone", mIsActivated ? currentStatus : 0);

//        Intent mIntent = new Intent(Constants.ACTION_REFUSE_PHONE);
//        mIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND | InternalConstant.FLAG_RECEIVER_INCLUDE_BACKGROUND);
//        mIntent.putExtra(Constants.EXTRA_REFUSE_PHONE, mIsActivated ? currentStatus : 0);
    }


    /**
     * 检查设备状态，判断是否需要发送开启/关闭禁止关机功能
     */
    @SuppressLint("WrongConstant")
    public void checkProhibitShutdownState(int currentStatus) {
        if (mProhibitShutdownStatus != currentStatus) {
            mProhibitShutdownStatus = currentStatus;
            Log.d(TAG, "checkProhibitShutdownState: " + currentStatus);
            Intent mIntent = new Intent(Constants.ACTION_PROHIBIT_SHUTDOWN);
            mIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND | InternalConstant.FLAG_RECEIVER_INCLUDE_BACKGROUND);
            mIntent.putExtra(Constants.EXTRA_PROHIBIT_SHUTDOWN, mIsActivated ? currentStatus : 0);
        }
    }


    /**
     * 检查设备状态，判断是否需要开启脱落监听
     */
    public void checkFallOffAlarmState(int currentStatus) {

        if (mFallOffAlarmSatus != currentStatus) {
            mFallOffAlarmSatus = currentStatus;
            boolean operateFlag = mIsActivated && currentStatus == 1;
            Log.d(TAG, "checkFallOffAlarmState operateFlag: " + operateFlag);
            if (operateFlag) {
                FalloffObserver.getInstance().registerSensor();
            } else {
                FalloffObserver.getInstance().unRegisterSensor();
            }
        }

    }
}
